package com.donghua.controller;

import com.donghua.entity.LoginTicket;
import com.donghua.entity.Picture;
import com.donghua.entity.User;
import com.donghua.service.DiscussPostService;
import com.donghua.service.FollowService;
import com.donghua.service.UserService;
import com.donghua.util.*;
import com.donghua.vo.UserDetailInfo;
import net.coobird.thumbnailator.Thumbnailator;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import static com.donghua.enums.StatusCodeEnum.*;
import static com.donghua.util.CommunityConstant.ENTITY_TYPE_USER;
import static javax.imageio.ImageIO.*;

@Controller
@RequestMapping("/users")
public class UserController {

    private static final Logger logger = LoggerFactory.getLogger(UserController.class);

    @Value("${community.path.upload}")
    private String uploadPath;

    @Value("${community.path.domain}")
    private String domain;

    @Value("${server.servlet.context-path}")
    private String contextPath;

    @Autowired
    private UserService userService;

    @Autowired
    private HostHolder hostHolder;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private FollowService followService;

    @RequestMapping(path = "/nickName", method = RequestMethod.POST)
    @ResponseBody
    public Result<?> updateNickName(String nickName) {

        if(nickName == null) {
            return Result.ok(USER_NICKNAME_ERROR.getCode(), USER_NICKNAME_ERROR.getMsg());
        }

        User user1 = userService.findUserByNickName(nickName);
        if(user1 != null) {
            return Result.ok(NICKNAME_EXIST.getCode(), NICKNAME_EXIST.getMsg());
        }
        User user = hostHolder.getUser();
        userService.updateNickName(user.getId(), nickName);
        return Result.ok(SUCCESS.getCode(), SUCCESS.getMsg());
    }

    @RequestMapping(path = "/description", method = RequestMethod.POST)
    @ResponseBody
    public Result<?> updateDescription(String description) {
        if(description == null) {
            return Result.ok(USER_DESCRIPION_ERROR.getCode(), USER_DESCRIPION_ERROR.getMsg());
        }
        User user = hostHolder.getUser();
        userService.updateDescription(user.getId(), description);
        return Result.ok(SUCCESS.getCode(), SUCCESS.getMsg());
    }


    @RequestMapping(path = "/header", method = RequestMethod.POST)
    @ResponseBody
    public Result<?> uploadHeader(MultipartFile file) {
        if (file == null) {
            return Result.ok(NO_SELECTED_HEADER.getCode(), NO_SELECTED_HEADER.getMsg());
        }

        String fileName = file.getOriginalFilename();
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        if (StringUtils.isBlank(suffix)) {
            return Result.ok(FILE_FORMAT_ERROR.getCode(), FILE_FORMAT_ERROR.getMsg());
        }

        // 生成随机文件名
        fileName = CommunityUtil.generateUUID() + suffix;
        // 确定文件存放的路径
        File dest = new File(uploadPath + "/" + fileName);
        try {
            // 存储文件
            file.transferTo(dest);
        } catch (IOException e) {
            logger.error("上传文件失败: " + e.getMessage());
            throw new RuntimeException("上传文件失败,服务器发生异常!", e);
        }

        // 更新当前用户的头像的路径(web访问路径)
        // http://localhost:8081/users/image/xxx.png
        User user = hostHolder.getUser();
        String headerUrl = domain + contextPath + "/users/image/" + fileName;
        userService.updateHeader(user.getId(), headerUrl);

        return Result.ok(SUCCESS.getCode(), SUCCESS.getMsg());
    }

    @RequestMapping(path = "/background", method = RequestMethod.POST)
    @ResponseBody
    public Result<?> uploadBackground(MultipartFile file) {
        if (file == null) {
            return Result.ok(NO_SELECTED_BACKGROUND.getCode(), NO_SELECTED_BACKGROUND.getMsg());
        }

        String fileName = file.getOriginalFilename();
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        if (StringUtils.isBlank(suffix)) {
            return Result.ok(FILE_FORMAT_ERROR.getCode(), FILE_FORMAT_ERROR.getMsg());
        }

        // 生成随机文件名
        fileName = CommunityUtil.generateUUID() + suffix;
        // 确定文件存放的路径
        File upload = new File(uploadPath);
        if(!upload.exists()) {
            upload.mkdirs();
        }
        File dest = new File(uploadPath + "/" + fileName);
        try {
            // 存储文件
            file.transferTo(dest);
        } catch (IOException e) {
            logger.error("上传文件失败: " + e.getMessage());
            throw new RuntimeException("上传文件失败,服务器发生异常!", e);
        }
        // 更新当前用户的背景的路径(web访问路径)
        // http://localhost:8081/users/image/xxx.png
        User user = hostHolder.getUser();
        String backgroundUrl = domain + contextPath + "/users/image/" + fileName;
        userService.updateBackGround(user.getId(), backgroundUrl);

        return Result.ok(SUCCESS.getCode(), SUCCESS.getMsg());
    }


    @RequestMapping(path = "/image/{fileName}", method = RequestMethod.GET)
    public void getHeaderOrBackground(@PathVariable("fileName") String fileName, @RequestParam(value = "width", defaultValue = "9999") int width , @RequestParam(value = "height", defaultValue = "1000") int height, HttpServletResponse response) throws IOException {
        String newFIleName = uploadPath + "/" + width + fileName;
        // 服务器存放路径
        fileName = uploadPath + "/" + fileName;
        // 文件后缀
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        // 响应图片
        response.setContentType("image/" + suffix);
        File newFile = new File(newFIleName);
        if(width == 9999)
        {
            Thumbnails.of(fileName).scale(1f).toFile(newFile);
        }else{
            Thumbnails.of(fileName).size(width, height).toFile(newFile);
        }
        try (
                FileInputStream fis = new FileInputStream(newFile);
                OutputStream os = response.getOutputStream();
        ) {
            byte[] buffer = new byte[1024];
            int b = 0;
            while ((b = fis.read(buffer)) != -1) {
                os.write(buffer, 0, b);
            }
        } catch (IOException e) {
            logger.error("读取头像失败: " + e.getMessage());
        }
    }


    @RequestMapping(path = "/info", method = RequestMethod.GET)
    @ResponseBody
    public Result<?> getUserInfo(@CookieValue("ticket") String ticket) {

        //获取ticket实体
        //通过ticket获取到user
        String redisKey = RedisKeyUtil.getTicketKey(ticket);
        LoginTicket loginTicket =  (LoginTicket) redisTemplate.opsForValue().get(redisKey);
        User user = userService.findUserById(loginTicket.getUserId());
        //将user存入data中的user
        Map<String, Object> data = new HashMap<>();
        UserDetailInfo userDetailInfo = new UserDetailInfo();
        userDetailInfo.setId(user.getId());
        userDetailInfo.setNickName(user.getNickName());
        userDetailInfo.setDescription(user.getDescription());
        userDetailInfo.setUsername(user.getUsername());
        userDetailInfo.setType(user.getType());
        userDetailInfo.setStatus(user.getStatus());
        userDetailInfo.setCreateTime(user.getCreateTime());
        userDetailInfo.setHeaderUrl(user.getHeaderUrl());
        userDetailInfo.setBackgroundUrl(user.getBackgroundUrl());
        data.put("user", userDetailInfo);
        return Result.ok(SUCCESS.getCode(), SUCCESS.getMsg(), data);
    }

    // 个人信息：包括关注了多少人，有多少粉丝，获得了多少的赞（文章）
    @RequestMapping(path = "/profile/{userId}", method = RequestMethod.GET)
    @ResponseBody
    public Result<?> getProfilePage(@PathVariable("userId") int userId, HttpServletRequest request) {
        User user = userService.findUserById(userId);
        if (user == null) {
            throw new RuntimeException("该用户不存在!");
        }
        // 用户信息
        Map<String, Object> data = new HashMap<>();
        UserDetailInfo userDetailInfo = new UserDetailInfo();
        userDetailInfo.setId(user.getId());
        userDetailInfo.setNickName(user.getNickName());
        userDetailInfo.setDescription(user.getDescription());
        userDetailInfo.setUsername(user.getUsername());
        userDetailInfo.setType(user.getType());
        userDetailInfo.setStatus(user.getStatus());
        userDetailInfo.setCreateTime(user.getCreateTime());
        userDetailInfo.setHeaderUrl(user.getHeaderUrl());
        userDetailInfo.setBackgroundUrl(user.getBackgroundUrl());
        data.put("user", userDetailInfo);

        // 关注数量
        long followeeCount = followService.findFolloweeCount(userId, ENTITY_TYPE_USER);
        data.put("followeeCount", followeeCount);
        // 粉丝数量
        long followerCount = followService.findFollowerCount(ENTITY_TYPE_USER, userId);
        data.put("followerCount", followerCount);
        // 从cookie中获取凭证
        String ticket = CookieUtil.getValue(request, "ticket");
        boolean flag = false;
        if (ticket != null) {
            // 查询凭证
            String redisKey = RedisKeyUtil.getTicketKey(ticket);
            LoginTicket loginTicket = (LoginTicket) redisTemplate.opsForValue().get(redisKey);
            // 检查凭证是否有效
            if (loginTicket != null && loginTicket.getStatus() == 0 && loginTicket.getExpired().after(new Date())) {
                // 根据凭证查询用户
                User user1 = userService.findUserById(loginTicket.getUserId());
                hostHolder.setUser(user1);
                flag = true;
            }
        }
        // 是否已关注
        boolean hasFollowed = false;
        if (flag) {
            hasFollowed = followService.hasFollowed(hostHolder.getUser().getId(), ENTITY_TYPE_USER, userId);
        }
        data.put("hasFollowed", hasFollowed);

        return Result.ok(SUCCESS.getCode(), SUCCESS.getMsg(), data);
    }

}
